package com.zboin.framework.config.alioss;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.Protocol;
import com.aliyun.oss.model.OSSObject;
import com.zboin.common.exception.BusinessException;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author zhboom
 * @date 2023-08-21
 *
 * 阿里云 OSS 操作对象
 */
@Slf4j
@Component
public class AliOssClient {

    private final OssProperties ossProperties;

    public AliOssClient(OssProperties ossProperties) {
        this.ossProperties = ossProperties;
    }

    public OSS ossClient;

    @PostConstruct
    public void init() {
        ossClient = createOssClient();
    }

    @PreDestroy
    public void destroy() {
        if (ossClient != null) {
            ossClient.shutdown();
        }
    }

    private OSS createOssClient() {
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();

        // 设置OSSClient允许打开的最大HTTP连接数，默认为1024个。
        conf.setMaxConnections(200);
        // 设置Socket层传输数据的超时时间，默认为50000毫秒。
        conf.setSocketTimeout(60000);
        // 设置建立连接的超时时间，默认为50000毫秒。
        conf.setConnectionTimeout(30000);
        // 设置连接空闲超时时间。超时则关闭连接，默认为60000毫秒。
        conf.setIdleConnectionTime(60000);
        // // 设置失败请求重试次数，默认为3次。
        conf.setMaxErrorRetry(3);
        // // 设置连接OSS所使用的协议（HTTP或HTTPS），默认为HTTP。
        conf.setProtocol(Protocol.HTTPS);

        return new OSSClientBuilder().build(
                ossProperties.getEndPoint(),
                ossProperties.getClientId(),
                ossProperties.getClientSecret(),
                conf);
    }

    /**
     * 上传文件到ali oss
     * @param fileName 上传的文件路径名
     * @return 文件访问路径
     */
    public String uploadFile(String fileName, InputStream inputStream) {
        ossClient.putObject(ossProperties.getBucketName(), fileName, inputStream);
        log.info("success upload file to alis oss: {}", fileName);
        return ossProperties.getBucketUrl() + fileName;
    }

    /**
     * 基于文件名称判断文件是否存在
     * @param fileName 文件名称
     * @return 是否存在
     */
    public boolean fileExists(String fileName) {
        return ossClient.doesObjectExist(ossProperties.getBucketName(), fileName);
    }

    /**
     * 删除 ali oss 上的文件
     * @param fileName 文件路径
     */
    public void deleteFile(String fileName) {
        String realFile = fileName.replace(ossProperties.getBucketUrl(), "");
        ossClient.deleteObject(ossProperties.getBucketName(), realFile);
    }

    /**
     * 读取文件内容为字节数组
     * @param filename 文件名称
     * @return 字节数组
     */
    public byte[] getObjectBytes(String filename) {
        String realFile = filename.replace(ossProperties.getBucketUrl(), "");
        OSSObject ossObject = ossClient.getObject(ossProperties.getBucketName(), realFile);
        InputStream inputStream = ossObject.getObjectContent();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try (ossObject; inputStream; bos) {
            byte[] buffer = new byte[1024];
            int read;
            while ((read = inputStream.read(buffer)) != -1) {
                bos.write(buffer, 0, read);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            throw new BusinessException(1002, e.getMessage());
        }
    }
}
